import cloneDeep from 'lodash/cloneDeep';

const pointXSpace = 150;    //节点间固定x间隔
let pointYSpace ;    //节点间固定y间隔
let translatePointY = pointXSpace + 40; //竖直情况下 所有节点向上移动距离；
const branchLevelRate = 0.7; //分支首尾两端和普通节点间距的比例
let pointYoffset = 50;   //图形距离顶部偏移量
const pointXoffset = 0;     //图形距离右侧偏移量

let freeNodePoint = {};
let freeNodePointCache = {};

const limitX = 1000;
let currentRow = 1;
let currentElementX = 0;
let currentElementY = 0;
let rowSpace = 100;
let _cachePoints = {};
let _points = {};
let eachRowHeight = {}; //存储每行的最大高度 不包含偏移量

/**
 *
 *
 * @param rootElement
 */
export const calculateNodePoint = (rootElement = {}, offsetY=50 , freeNodeLength=1) => {
    currentRow = 1;
    currentElementX = 0;
    currentElementY = 0;

    freeNodePoint = {};
    freeNodePointCache = {};
    pointYoffset = offsetY;
    translatePointY = pointXSpace + 40 + (-freeNodeLength*5);

    if(calculateIsExistedBranch(rootElement)){
        pointYSpace = 148;
    }else{
        pointYSpace = window.testnum || 256;//254
    }

    let t1 = new Date().getTime();
    let height = calculateNextElementPos(rootElement);

    // calculateElement(rootElement);
    // console.log(_cachePoints,'_cachePoints',freeNodePointCache);

    //console.log("rootElement",rootElement);
    //console.log("height",height,freeNodePointCache);
    calculateNextElementPoint(rootElement, height, 1, 0);
    const {id} = rootElement;
    freeNodePointCache[`branch_max_height_${id}`] = height;
    console.log("计算耗时", new Date().getTime() - t1);
    //console.log("freeNodePoint", freeNodePoint);

    return freeNodePoint;
    // return _cachePoints;
}
/************** 检测 数据是否存在分支，如不存在 向右间隔做调整*/
const calculateIsExistedBranch = (element = {}) => {
    const { nodeElement = true , hasNext = false , next = {} , parallelNodeGroupDatas=[]} = element;
    let res = false;
    if(!nodeElement){
        res = true;
    }
    if(hasNext){
       let _res = calculateIsExistedBranch(next); 
       _res ? res = _res : '';
    }
    parallelNodeGroupDatas.map(v=>{
        let _res = calculateIsExistedBranch(v); 
       _res ? res = _res : '';
    });
    return res;
}
/***************************************************/

let currentRowElement = [];
const calculateElement = (element = {}) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = element;

    let curElementHeight = {};
    if(nodeElement){
        if(currentRow % 2 == 0){ //向左流向
            currentElementX -= pointXSpace;
            if(currentElementX < 0){ // 换行
                currentRow ++;
                currentElementX = 0;
                currentElementY += rowSpace;
                currentRowElement = [];
            }
        }else{//向右流向
            currentElementX += pointXSpace;
            if(currentElementX > limitX){ //换行
                currentRow ++;
                currentElementX = limitX;
                currentElementY += rowSpace;
                currentRowElement = [];
            }
        }
        curElementHeight[id]= calculateElementHeight(element);//记录当前元素的高度
        currentRowElement.push(curElementHeight);
        // _cachePoints[`x_${id}`] = currentElementX;
        // _cachePoints[`y_${id}`] = currentElementY + pointYoffset;
        _cachePoints[`${id}_point`] = {
            x : currentElementX,
            y : currentElementY + pointYoffset
        }
    }else{
        if(currentRow % 2 == 0){
            currentElementX -= pointXSpace;
        }else{
            currentElementX += pointXSpace;
        }
    }
    if(hasNext){
        calculateElement(next);
    }
}
/**
    获取元素高度
 */
const calculateElementHeight = (element = {}) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = element;

    let nodeMaxHeight = 0;
    let branchMaxHeight = 0;
    if(nodeElement){
        nodeMaxHeight = calculateNodeHeight(element);
        if(hasNext){
            let _nextEltMaxHeight = calculateElementHeight(next);
            nodeMaxHeight = _nextEltMaxHeight > nodeMaxHeight ? _nextEltMaxHeight / 2 + pointYoffset : nodeMaxHeight;
        }
    }else{
        branchMaxHeight = calculateBranchHeight(element);
    }
    return branchMaxHeight > nodeMaxHeight ? branchMaxHeight : nodeMaxHeight;
}
/**
    获取节点高度
 */
const calculateNodeHeight = (element = {}) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = element;
}
/**
    获取分支元素高度
 */
const calculateBranchHeight = (element = {}) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = element;
}

/***************************************************/
/**
 *
 * @param elements
 */
const calculateParallelNodePos = (elements = [],) => {
    let length = elements.length;
    let sumHight = 0;
    elements.map((element, index) => {
        let itemMaxHeight = calculateNextElementPos(element);
        sumHight += itemMaxHeight;
        const {id} = element;
        freeNodePointCache[`branch_max_height_${id}`] = itemMaxHeight;
    })
    return sumHight;
}

/**
 * 计算下一节点
 * @param nextElement
 */
const calculateNextElementPos = (nextElement = {}) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = nextElement;

    //console.log("nextElement",nextElement);
    //节点下一元素
    let nextElementHeight = 0;
    let currentElementHeight = 0;
    if (hasNext) {
        nextElementHeight = calculateNextElementPos(next);
    }

    //计算并行节点
    if (parallelNodeGroupDatas.length > 0) {
        currentElementHeight = calculateParallelNodePos(parallelNodeGroupDatas);
    }

    if (!hasNext && nodeElement) {
        currentElementHeight = pointYSpace;
    } else {
        //当前节点非当前分支最后一个节点，且是串行节点
        if (currentElementHeight == 0) {
            currentElementHeight = pointYSpace;
        }
    }
    freeNodePointCache[id] = currentElementHeight;
    return currentElementHeight > nextElementHeight ? currentElementHeight : nextElementHeight;
}

const calculateParallelElementPoint = (elements = [], level, yOffset) => {
    let branchMaxLevel = level;
    let branchOffset = yOffset;
    elements.map((element, index) => {
        const {id} = element;
        const branchMaxHeight = freeNodePointCache[`branch_max_height_${id}`];
        let itemLevel = calculateNextElementPoint(element, branchMaxHeight, level, branchOffset,true);
        branchMaxLevel = itemLevel > branchMaxLevel ? itemLevel : branchMaxLevel;
        branchOffset += branchMaxHeight;
    })
    return branchMaxLevel;
}

/**
 *
 * @param nextElement
 * @param branchMaxHeight
 * @param level
 * @param index
 * @param branchCount
 * @param parentBranchMaxHeight
 * @return {number}
 */
const calculateNextElementPoint = (nextElement = {}, branchMaxHeight = 0, level = 1, yOffset = 0 , inBranch = false , preNode = null) => {
    const {id, hasNext = false, next = {}, parallelNodeGroupDatas = [], nodeEntity = {}, nodeElement = false} = nextElement;
    let currentLevel = level;
    // console.log("branchMaxHeight",branchMaxHeight, id, index,yOffset);
    let elementHeight = freeNodePointCache[id];
    if (nodeElement) {
        if(inBranch){//属于分支第一层节点
            currentLevel = currentLevel + branchLevelRate;
        }else if(preNode && !preNode.nodeElement){
            currentLevel = currentLevel + 0.7;
        }else{
            currentLevel ++;
        }
        let pointX = currentLevel * pointXSpace + pointXoffset;
        let pointY = 0;
        if (branchMaxHeight > elementHeight) {
            pointY = branchMaxHeight / 2 + pointYoffset + yOffset;
        } else {
            pointY = yOffset + pointYoffset + elementHeight / 2;
        }
        freeNodePoint[`${id}_point`] = {y: pointX - translatePointY, x: pointY};//所有的 点统一向上靠（pointXSpace + 40）
    }

    //计算一个虚拟分叉起始点
    if (parallelNodeGroupDatas.length > 0) {
        if(preNode && !preNode.nodeElement){
            currentLevel = currentLevel + 0.5;
        }else{
            currentLevel = currentLevel + branchLevelRate;
        }
        let pointX = currentLevel * pointXSpace + pointXoffset;
        let pointY = branchMaxHeight / 2 + yOffset + pointYoffset;
        freeNodePoint[`${id}_virtual_branch_point`] = {y: pointX - translatePointY, x: pointY,virtual:true,isBranch:true};

        let branchYOffset = yOffset;
        let branchSumHeight = calculateBranchSumHeight(parallelNodeGroupDatas);
        if(branchSumHeight < branchMaxHeight) {
            branchYOffset +=  (branchMaxHeight - branchSumHeight) / 2;
        }
        //console.log("branchYOffset",id,branchYOffset,branchSumHeight,branchMaxHeight,yOffset);
        //计算并行节点
        currentLevel = calculateParallelElementPoint(parallelNodeGroupDatas, currentLevel, branchYOffset);

        //计算一个虚拟合并节点位置
        currentLevel = currentLevel + branchLevelRate;
        pointX = currentLevel * pointXSpace + pointXoffset;
        pointY = branchMaxHeight / 2 + yOffset + pointYoffset;
        freeNodePoint[`${id}_virtual_merge_point`] = {y: pointX - translatePointY, x: pointY,virtual:true,isMerge:true};
    }
    if (hasNext) {
        currentLevel = calculateNextElementPoint(next, branchMaxHeight, currentLevel,yOffset,false,nextElement);
    }
    return currentLevel;
}

const calculateBranchSumHeight = (parallelNodeGroupDatas = []) => {
    let height = 0;
    parallelNodeGroupDatas.map((element, index) => {
        const {id} = element;
        const branchMaxHeight = freeNodePointCache[`branch_max_height_${id}`];
        height += branchMaxHeight;
    })
    return height;
}

